<?php
/**
 *
 * @author Strawberry🍓
 * @date 2021-06-25 2:01 下午
 *
 */

namespace app\common\controller;


use app\common\model\tang\MerchantMobile;
use think\facade\Log ;

class Socket
{
    protected static $socket_ip = '120.92.105.112';
    protected static $port = 8802;

    public function connSocket($room_id,$type,$BuyNum,$Amount,$order_sn,$openid){
        if (!$room_id){
            return 'room_id不能为空';
        }
        if (!$type){
            return 'type不能为空';
        }
        if (!$BuyNum){
            return 'BuyNum不能为空';
        }
        if (!$Amount){
            return 'Amount不能为空';
        }
        if (!$order_sn){
            return 'order_sn不能为空';
        }
        if (!$openid){
            return 'openid不能为空';
        }
        $EngType = '';
        // 1电  5水
        if ($type == 1){
            $EngType = 2;
        }
        if ($type == 5){
            $EngType = 1;
        }
        $result = $this->getMemberInfo($room_id);
        if (!$result){
            return '房间号不存在';
        }
        if (!isset($result['RoomList']) || !$result['RoomList']){
            return '房间号不存在';
        }
        $reqRoomId  = $result['RoomList']['Room']['RoomID'];
        //请求表具
        $buyInfo = $this->getBuyInfo($reqRoomId);
        if (!$buyInfo){
            return '表具不存在';
        }
        if (!isset($buyInfo['MeterList']['Meter']) || !$buyInfo['MeterList']['Meter']){
            return '表具不存在';
        }
        $MeterInfo = [];
        $MeterList = $buyInfo['MeterList']['Meter'];
        foreach ($MeterList as $key=>$value){
            if ($EngType == $value['EngType']){
                $MeterInfo = $MeterList[$key];
                break;
            }
        }
        if (empty($MeterInfo)){
            return '表具不存在';
        }
        $MetID = $MeterInfo['MetID'];
        $giveAmonut = $this->giveAmonut($MetID,$BuyNum);
        Log::record('-----------giveAmonut------------------');
        Log::record(json_encode($giveAmonut));
        if (!$giveAmonut){
            return '充值失败';
        }
        $TopupAmount = $this->TopupAmount($reqRoomId,$Amount,$MetID,$order_sn,$openid);
        Log::record('-----------TopupAmount------------------');
        Log::record(json_encode($TopupAmount));
        if (!$TopupAmount){
            return '充值失败';
        }
        return '充值成功';
    }

    /**
     * 查询用户信息
     * @return false|string
     */
    public function getMemberInfo($room_id){
        $socket = self::getSocketStream();  //创建socket连接
        if($socket == false){
            return false;
        }
        $arr = [
            'TradeCode'   => '40801', //交易码
            'TradeTime'   => date('Ymdhis'), //date('Ymdhis', time())交易时间
            'BankID'      => '20001',//银行编号
            'TermType'    => '3', //终端类型
            'TermID'      => 'opxxxxxx', //终端号
            'ClientID'    => 'Test', //客户编号
            'AreaCodeS'   => '00010001', //小区编号
            'QueryType'   => '4', //查询方式
            'SearchKey'   => '3',
            'UserCode'    => $room_id,
            'UserPW'    => '1',
            'ISVerifyPW'    => '1',
        ];
        $data = self::arrayToSignXml(40801,$arr);
        socket_write($socket,$data);
        $result = '';
        while($out = socket_read($socket,102400)) {
//            $result .= iconv("utf-8","gb2312//IGNORE",$out);
            $result .= iconv("gb2312//IGNORE","utf-8",$out);
        }
        socket_close($socket);
        Log::record('-----------请求房间号码------------------');
        Log::record("请求房间号码{$result}");
//        $this->app->log->info("请求房间号码{$result}");
        preg_match('/<PacketXML>.*<\/PacketXML>/',$result,$info);
        if (empty($info)){
            return false;
        }
        if (!isset($info[0]) && empty($info[0])){
            return false;
        }
        $objectxml = simplexml_load_string($info[0]);//将文件转换成 对象
        $xmljson= json_encode($objectxml );//将对象转换个JSON
        $xmlarray=json_decode($xmljson,true);//将json转换成数组
        if ($xmlarray['RespCode'] != 0){
            return $xmlarray['RespMsg'];
        }
        return $xmlarray;
    }
    // 额
    public function getBuyInfo($RoomID){
        $socket = self::getSocketStream();  //创建socket连接
        if($socket == false){
            return false;
        }
        $arr = [
            'TradeCode'   => '40803', //交易码
            'TradeTime'   => date('Ymdhis'), //date('Ymdhis', time())交易时间
            'BankID'      => '20001',//银行编号
            'TermType'    => '3', //终端类型
            'TermID'      => 'opxxxxxx', //终端号
            'ClientID'    => 'Test', //客户编号
            'QueryType'   => '0', //查询方式
            'RoomID'      => $RoomID,
            'CardID'      => '',
            'ReadCardData'=> '',
        ];
        $data = self::arrayToSignXml(40803,$arr);
        socket_write($socket,$data);
        $result = '';
        while($out = socket_read($socket,102400)) {
            $result .= iconv("gb2312//IGNORE","utf-8",$out);
        }
        socket_close($socket);
        Log::record('-----------请求房间号码------------------');
        Log::record("请求房间号码{$result}");
//        $this->app->log->info("请求房间号码{$result}");
        preg_match('/<PacketXML>.*<\/PacketXML>/',$result,$info);
        if (empty($info)){
            return false;
        }
        if (!isset($info[0]) && empty($info[0])){
            return false;
        }
        $objectxml = simplexml_load_string($info[0]);//将文件转换成 对象
        $xmljson= json_encode($objectxml );//将对象转换个JSON
        $xmlarray=json_decode($xmljson,true);//将json转换成数组
        if ($xmlarray['RespCode'] != 0){
            return $xmlarray['RespMsg'];
        }
        return $xmlarray;
    }


    public function giveAmonut($MetID,$BuyNum){
        $socket = self::getSocketStream();  //创建socket连接
        if($socket == false){
            return false;
        }
        $arr = [
            'TradeCode'   => '40804', //交易码
            'TradeTime'   => date('Ymdhis'), //date('Ymdhis', time())交易时间
            'BankID'      => '20001',//银行编号
            'TermType'    => '3', //终端类型
            'TermID'      => 'opxxxxxx', //终端号
            'ClientID'    => 'Test', //客户编号
            'MetID'   => $MetID,
            'BuyNum'      => $BuyNum,
            'WriteCardStatus'      => 1,
        ];
        $data = self::arrayToSignXml(40804,$arr);
        socket_write($socket,$data);
        $result = '';
        while($out = socket_read($socket,102400)) {
            $result .= iconv("gb2312//IGNORE","utf-8",$out);
        }
        socket_close($socket);
        Log::record('-----------请求房间号码------------------');
        Log::record("请求房间号码{$result}");
//        $this->app->log->info("请求房间号码{$result}");
        preg_match('/<PacketXML>.*<\/PacketXML>/',$result,$info);
        if (empty($info)){
            return false;
        }
        if (!isset($info[0]) && empty($info[0])){
            return false;
        }
        $objectxml = simplexml_load_string($info[0]);//将文件转换成 对象
        $xmljson= json_encode($objectxml );//将对象转换个JSON
        $xmlarray=json_decode($xmljson,true);//将json转换成数组
        if ($xmlarray['RespCode'] != 0){
            return $xmlarray['RespMsg'];
        }
        return $xmlarray;
    }





    /**
     * 电费充值
     * @param $RoomID
     * @param $UserID
     * @param $PaySerialNo
     * @param $Amount
     * @return false|string
     */
    public function TopupAmount($RoomID, $Amount, $MetID,$BankSerial,$Openid)
    {
        $socket = self::getSocketStream();  //创建socket连接
        if($socket == false){
            return false;
        }

        $xml = '<PacketXML><AccountNo></AccountNo><BankID>20001</BankID><BankSerial>'.$BankSerial.'</BankSerial><BuyList><Buy><MetID>'.$MetID.'</MetID></Buy></BuyList><CardData></CardData><CardType></CardType><ClientID>Test</ClientID><DiscountList/><FactMoney>'.$Amount.'</FactMoney><IsEmergency>0</IsEmergency><PostList/><PostMoneyTotal>0.00</PostMoneyTotal><ProMoneyTotal>'.$Amount.'</ProMoneyTotal><ProcedureFee>0.00</ProcedureFee><QueryType>0</QueryType><ReadCardData></ReadCardData><RoomID>'.$RoomID.'</RoomID><ShowType>1</ShowType><TermID>'.$Openid.'</TermID><TermType>3</TermType><TradeCode>40805</TradeCode><TradeTime>20210702154703</TradeTime></PacketXML>';
        $tmpMD5 = strtoupper(md5($xml.'CE04089E-C1FF-4A7E-AB92-35D7365952E6'));
        $xml = '40805'.$xml;
        $data =  self::myStrlen($xml).$xml.$tmpMD5;
        socket_write($socket,$data);
        $result = '';
        while($out = socket_read($socket,8192)) {
            $result .= iconv("utf-8","gb2312//IGNORE",$out);
        }
        socket_close($socket);
        Log::record('-----------请求房间号码------------------');
        Log::record("请求房间号码{$result}");
//        $this->app->log->info("请求房间号码{$result}");
        preg_match('/<PacketXML>.*<\/PacketXML>/',$result,$info);
        if (empty($info)){
            return false;
        }
        if (!isset($info[0]) && empty($info[0])){
            return false;
        }
        $objectxml = simplexml_load_string($info[0]);//将文件转换成 对象
        $xmljson= json_encode($objectxml );//将对象转换个JSON
        $xmlarray=json_decode($xmljson,true);//将json转换成数组
        Log::record('-----------RespCode------------------');
        Log::record($xmlarray['RespCode']);
        if ($xmlarray['RespCode'] == '0000' || $xmlarray['RespCode']== '0519' || $xmlarray['RespCode'] == '0513'){
            return true;
        }
        return  false;;
    }

    /**
     * 创建socket对象
     * @return false|resource|\Socket
     */
    protected static function getSocketStream(){
        /****************创建一个socket套接流****************/
        if (!($socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
            var_dump("Error Creating Socket: ".socket_strerror(socket_last_error()));
            return false;
        }
        /****************设置socket连接选项*************/
        //接收套接流的最大超时时间60秒，后面是微秒单位超时时间，设置为零，表示不管它
        socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 60, "usec" => 0));
        //发送套接流的最大超时时间为60秒
        socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec" => 60, "usec" => 0));
        /****************连接服务端的套接流****************/

        $stream = socket_connect($socket,  self::$socket_ip, self::$port);
        if ($stream < 0) {
            var_dump("socket_connect() failed.\nReason: ($stream) " . socket_strerror($stream) . "\n");
            return false;
        }
        return $socket;
    }

    /**
     * 生成包含加密签名的XML
     * @param $tradeCode
     * @param $arr
     * @return string
     */
    protected function arrayToSignXml($tradeCode, $arr){
        $xml = self::myArrayToXml($arr);
        $tmpMD5 = strtoupper(md5($xml.'CE04089E-C1FF-4A7E-AB92-35D7365952E6'));
        $xml = $tradeCode.$xml;
        return self::myStrlen($xml).$xml.$tmpMD5;
    }


    /**
     * 生成专用XML
     * @param $arr
     * @return string
     */
    protected static function myArrayToXml($arr)
    {
        $xml = "<PacketXML>";
        foreach ($arr as $key => $val) {
            if (is_array($val)) {
                $xml .= "<" . $key . ">" . self::myArrayToXml($val) . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            }
        }
        $xml .= "</PacketXML>";
        return $xml;
    }


    /**
     * 生成专用字符串长度
     * @param $str
     * @return string
     */
    protected static function myStrlen($str) :string{
        $count = strlen($str);
        $sumCount = 5-strlen($count);
        for ($i=0;$i<$sumCount;$i++) {
            $count = '0'.$count;
        }
        return $count;
    }

    /**
     * 获取随机字符串
     * @param $length
     * @return string
     */
    protected static function getRandStr($length){
        //字符组合
        $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $len = strlen($str)-1;
        $randstr = '';
        for ($i=0;$i<$length;$i++) {
            $num=mt_rand(0,$len);
            $randstr .= $str[$num];
        }
        return $randstr;
    }

}